package com.fatdetection.demo.config;

import com.fatdetection.demo.annotation.AuthAdmin;
import com.fatdetection.demo.annotation.AuthOperator;
import com.fatdetection.demo.annotation.AuthUser;
import com.fatdetection.demo.annotation.SuperAdmin;
import com.fatdetection.demo.util.TokenErrorMsg;
import com.fatdetection.demo.util.TokenUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.UnsupportedJwtException;
import io.jsonwebtoken.security.SignatureException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class RequestInterceptor implements HandlerInterceptor {
    @Autowired
    TokenUtils tokenUtils;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Value("${tokenRefreshTime}")
    Long tokenRefreshTime;

    @Value("${tokenExpTime}")
    Long tokenExpTime;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        System.out.println("-----拦截器拦截请求-----" + request.getRemoteHost());
        TokenErrorMsg tokenErrorMsg = new TokenErrorMsg(response);
        String authorization = request.getHeader("authorization");
        if(authorization == null){
            // token 不存在返回错误信息。
            tokenErrorMsg.noToken().sendMsg();
            return false;
        }
        if(!authorization.startsWith("Bearer ")){
            // token 格式不正确
            tokenErrorMsg.tokenNotValid().sendMsg();
            return false;
        }
        String token = authorization.replace("Bearer ", "");
        Claims claims;
        try {
            claims = tokenUtils.verifyToken(token);
        } catch (ExpiredJwtException e){
            claims = e.getClaims();
        } catch (UnsupportedJwtException | MalformedJwtException | SignatureException | IllegalArgumentException e){
            // token 不合法
            tokenErrorMsg.tokenNotValid().sendMsg();
            return false;
        }
        // 不管是否过期我们解析出 claims
        String redisToken = redisTemplate.opsForValue().get(token);
        if(redisToken == null){
            // 我们 redis 中的 token 过期了才是真正的过期了。也就是说过期的 token 我们仍然可以使用
            tokenErrorMsg.tokenOutDate().sendMsg();
            return false;
        }
        if(checkRole(claims, handler)){
            // token检测并刷新
            String outDateTimeFromRedis = redisTemplate.opsForValue().get(token);
            if(outDateTimeFromRedis != null){
                if(Long.parseLong(outDateTimeFromRedis) - new Date().getTime() <= tokenRefreshTime) {
                    // 时间已经小于 约定时间 刷新 token 的时间
                    redisTemplate.opsForValue()
                            .set(token
                            , String.valueOf(new Date(System.currentTimeMillis() + tokenExpTime * 1000).getTime())
                            , tokenExpTime, TimeUnit.SECONDS);
                }
            }
            return true;
        } else {
          // 权限不足
            tokenErrorMsg.writeTo("用户权限不足").sendMsg();
          return false;
        }
    }

    private boolean checkRole(Claims claims, Object handler){
        String role = claims.get("role").toString();
        // 获取登录用户的角色
        SuperAdmin superAdmin = ((HandlerMethod) handler).getMethod().getAnnotation(SuperAdmin.class);
        AuthAdmin authAdmin = ((HandlerMethod) handler).getMethod().getAnnotation(AuthAdmin.class);
        AuthUser authUser = ((HandlerMethod) handler).getMethod().getAnnotation(AuthUser.class);
        AuthOperator authOperator = ((HandlerMethod) handler).getMethod().getAnnotation(AuthOperator.class);
        Annotation[] annotations = ((HandlerMethod) handler).getBeanType().getAnnotations();
        List<Class<? extends Annotation>> rstList = new ArrayList<>();
        for (Annotation annotation : annotations) {
            rstList.add(annotation.annotationType());
        }
        if(rstList.contains(SuperAdmin.class)){
           if("3".equals(role)){
               return true;
           } else {
               return false;
           }
        }
        if (superAdmin != null) {
            if("3".equals(role)) {
                return true;
            } else {
                return false;
            }
        }
        if(rstList.contains(AuthAdmin.class)){
            if("1".equals(role) || "3".equals(role) || "2".equals(role)){
                return true;
            }
        }
        if(rstList.contains(AuthOperator.class)){
            if("1".equals(role) || "3".equals(role) || "2".equals(role)){
                return true;
            }
        }
        // 基于类上加注解的判断结束
        // 类上加的注解优先级大于方法。但是superadmin优先级大于类
        if (authAdmin != null){
            if ("1".equals(role) || "3".equals(role) || "2".equals(role)){
                return true;
            }
        }
        if (authOperator != null){
            if ("1".equals(role) || "3".equals(role) || "2".equals(role)){
                return true;
            }
        }
        if(authUser != null){
            if ("1".equals(role) || "3".equals(role) || "2".equals(role) || "0".equals(role)){
                return true;
            }
        }
        // 目前暂时操作员和管理员拥有相同的权限
        // 以上为最简单的实现，可整理优化代码
        return false;
    }


}
